package com.syf.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import sun.misc.BASE64Encoder;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 2.Web安全的配置
 *
 */
@Configuration
@EnableWebSecurity   //使其作为websecurity配置中心
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    //Spring Security 配置网络安全: http安全,资源的放行
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();   //配置csrf跨域(关闭跨域保护)
        http.authorizeRequests().anyRequest().authenticated(); //授权所有的请求

        /*http.authorizeRequests()
                .antMatchers("/**") //拦截所有路径
                .permitAll()    //处理方式
                .and()
                .httpBasic();   //通过httpBasic进行认证*/
    }

    /**
     * 重写authenticationManager 验证管理器:
     *      若不重写 AuthoricationServerConfig认证中心的AuthenticationManager 则无法注入
     *
     */
    @Override
    @Bean
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

   /* //创建一个测试的 UserDetail  模拟用户
    @Override
    @Bean
    public UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
        User user = new User("admin", "123456", Arrays.asList(new SimpleGrantedAuthority("Role_Admin")));
        inMemoryUserDetailsManager.createUser(user);
        return inMemoryUserDetailsManager;
    }*/

    /**
     * 注入密码的验证管理器(密码加密器)
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();  //加密
        //return NoOpPasswordEncoder.getInstance(); //不加密
    }


    //利用MD5进行加密,返回加密后的字符串
    public static String EncoderByMd5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        //确定计算方法
        MessageDigest md5= MessageDigest.getInstance("MD5");
        BASE64Encoder base64en = new BASE64Encoder();
        //加密后的字符串
        String newstr=base64en.encode(md5.digest(str.getBytes("utf-8")));
        return newstr;
    }

    //测试密码匹配器的效果
    public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        //加密器
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        //加密
        String encode = bCryptPasswordEncoder.encode("123456"); //加密后: $2a$10$Vkl4RqusKf3aTB9qtHCSyuJ588/O0a8Zs9wLRFJmxFpWm79CzTTwu
        //判断加密钱和加密后值是否相同: matches(明文["123456"/经过MD5加密后的]，密文)
        boolean code = bCryptPasswordEncoder.matches("123456", "$2a$10$Vkl4RqusKf3aTB9qtHCSyuJ588/O0a8Zs9wLRFJmxFpWm79CzTTwu");
        boolean code2 = bCryptPasswordEncoder.matches("4QrcOUm6Wau+VuBX8g+IPg==", "$2a$10$Vkl4RqusKf3aTB9qtHCSyuJ588/O0a8Zs9wLRFJmxFpWm79CzTTwu");

        System.out.println("加密后:"+encode);
        System.out.println("判断原文与bCryptPasswordEncoder加密: "+ code);
        System.out.println("判断MD5加密后与bCryptPasswordEncoder加密: "+ code2);


        /**
         * MD5:
         *   MD5是通过按照某个预定的规则，以固定长度为步长对数据进行转换，所以说它的数据转换过程其实是相当固化的,所以同样的密码经过MD5加密后结果是相同的
         *   md5算法是不可逆的，所以经过md5加密过的字符串是无法还原（解密）的。一般用作登陆验证的时候，也是要先经过md5加密然后去数据库验证密码是否正确
         */
        //System.out.println("判断原文与MD5加密后: "+ ("4QrcOUm6Wau+VuBX8g+IPg==".equals(EncoderByMd5("123456"))));
    }



}
